<template>
  <div class="view-editor">
    <div class="view-header">
      <div>视图编辑器</div>
      <div class="modal-header-buttons">
        <eButton type="primary" ghost @click="handlePreview">预览</eButton>
        <eButton type="primary" ghost @click="viewConfig">配置</eButton>
        <eButton type="primary" ghost @click="exportJson">导出</eButton>
        <eButton type="primary" ghost @click="importJson">导入</eButton>
      </div>
    </div>
    <div class="layout-container">
      <div class="comp-container">
        <!--左侧组件选择-->
        <CompAside
          :channel="props.channel"
          v-model:dragging="dragging"
        />
      </div>
      <div class="simulator-container">
        <!--模拟器-->
        <component
          ref="simulatorRef"
          :is="props.channel === 'pc' ? pcSimulator : mobileSimulator"
          :dragging="dragging"
          :initJson="initJson"
        />
      </div>
      <div class="attrs-container">
        <!--组件属性配置-->
        <AttrsAside />
      </div>
    </div>
  </div>

  <eModal
    v-model="modal.show"
    :mask-closable="false"
    footer-hide
    :title="modal.title"
    :width="modal.width"
  >
    <div v-if="modal.type === 'config'" style="width: 100%;height: 360px;">
      <MonacoEditor
        v-if="modal.loaded"
        v-model="configJsonStr"
        language="json"
        readOnly
      />
    </div>
    <div v-else-if="modal.type === 'preview'" style="min-height: 360px;">
      <PageMaking
        v-if="modal.show"
        v-bind="modal.props"
      />
    </div>
  </eModal>

  <Loading v-if="loading" />
</template>

<script setup lang="ts">
  import { nextTick, onMounted, reactive, ref } from 'vue'
  import CompAside from './components/comp-aside.vue';
  import AttrsAside from './components/attrs-aside.vue';
  import pcSimulator from './components/simulator/pc-simulator.vue'
  import mobileSimulator from './components/simulator/mobile-simulator.vue'
  import { ChannelEnum } from './types';

  interface IProps {
    code?: string
    channel?: `${ChannelEnum}`
  }

  const props = withDefaults(defineProps<IProps>(), {
    channel: ChannelEnum.PC
  })

  const initJson = ref<any>(null)
  const configJsonStr = ref('')
  const loading = ref(false)
  const dragging = ref(false)
  const modal = reactive({
    show: false,
    width: 800,
    title: '',
    loaded: false,
    type: '',
    props: {}
  })
  const simulatorRef = ref<InstanceType<typeof pcSimulator> | null>(null)

  function handlePreview() {
    modal.show = true
    modal.width = 1000
    modal.title = '预览'
    modal.type = 'preview'
    modal.props = {
      config: simulatorRef.value?.getConfig() || {}
    }
  }

  function viewConfig() {
    configJsonStr.value = JSON.stringify(simulatorRef.value?.getConfig() || {}, null, 2)
    modal.show = true
    modal.width = 800
    modal.title = '配置'
    modal.type = 'config'
    nextTick(() => {
      modal.loaded = true
    })
  }

  function exportJson() {
    const configJson = simulatorRef.value?.getConfig() || {}
    const formattedJson = JSON.stringify(configJson, null, 2)
    const blob = new Blob([formattedJson], { type: "application/json" })
    const url = URL.createObjectURL(blob)
    const a = document.createElement("a")
    a.href = url
    a.download = `${props.code || 'config'}.json`
    a.click()
    URL.revokeObjectURL(url)
  }

  function importJson() {
    const input = document.createElement('input')
    input.type = 'file'
    input.accept = '.json'
    input.onchange = (e: any) => {
      const file = e.target.files[0]
      const reader = new FileReader()
      reader.onload = (e: any) => {
        const json = JSON.parse(e.target.result)
        initJson.value = json
      }
      reader.readAsText(file)
    }
    input.click()
  }
</script>

<style lang="less" scoped>
  .view-editor {
    width: 100%;
    height: 100%;
    overflow: hidden;
  }
  .view-header {
    padding: 0 24px;
    height: 56px;
    background: #f0f0f0;
    display: flex;
    align-items: center;
    justify-content: space-between;
    .modal-header-buttons {
      margin-right: 24px;
      > *:not(:last-child) {
        margin-right: 16px;
      }
    }
  }
  .layout-container {
    width: 100%;
    height: calc(100% - 56px);
    display: flex;
    .comp-container, .attrs-container {
      width: 20%;
      height: 100%;
      overflow: auto;
      padding: 0 8px;
    }
    .simulator-container {
      width: 60%;
      height: 100%;
      overflow: hidden;
      padding: 4px 8px;
      background-color: #f7f7f7;
    }
  }
</style>